package com.caiden_micheal.dynamic.form_workflow.service.impl;

import com.caiden_micheal.base.constant.LoggerHead;
import com.caiden_micheal.base.domain.AjxResult;
import com.caiden_micheal.base.dto.PageDTO;
import com.caiden_micheal.base.utils.BaseContext;
import com.caiden_micheal.base.vo.PageVo;
import com.caiden_micheal.dynamic.form.domain.DynamicForm;
import com.caiden_micheal.dynamic.form.mapper.DFormMapper;
import com.caiden_micheal.dynamic.form_workflow.domain.FormWorkflow;
import com.caiden_micheal.dynamic.form_workflow.dto.*;
import com.caiden_micheal.dynamic.form_workflow.mapper.FormWorkflowMapper;
import com.caiden_micheal.dynamic.form_workflow.service.FormWorkflowService;
import com.caiden_micheal.dynamic.form_workflow.vo.FormWorkflowSelectDataVO;
import com.caiden_micheal.dynamic.form_workflow.vo.FormWorkflowVO;
import com.caiden_micheal.dynamic.process.domain.DynamicProcess;
import com.caiden_micheal.dynamic.process.mapper.DProcessMapper;
import com.caiden_micheal.dynamic.workflow.domain.DynamicWorkflow;
import com.caiden_micheal.dynamic.workflow.mapper.DWorkflowMapper;
import com.caiden_micheal.permission.domain.Permission;
import com.caiden_micheal.permission.mapper.PermissionMapper;
import com.caiden_micheal.permission.service.PermissionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class FormWorkflowServiceImpl implements FormWorkflowService {
    private static final Logger logger = LoggerFactory.getLogger(FormWorkflowServiceImpl.class);

    @Autowired
    private DFormMapper dFormMapper;
    @Autowired
    private DWorkflowMapper dWorkflowMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private FormWorkflowMapper formWorkflowMapper;
    @Autowired
    private PermissionService permissionService;
    @Autowired
    private DProcessMapper dProcessMapper;

    @Transactional
    @Override
    public AjxResult addFormWorkflow(AddFormWorkflowDTO addFormWorkflowDTO) {
        if (addFormWorkflowDTO == null || addFormWorkflowDTO.getWorkflowId() == null || addFormWorkflowDTO.getFormId() == null) {
            return AjxResult.paramError("参数传递有误");
        }
        if (addFormWorkflowDTO.getId() != null) {
            List<DynamicProcess> dynamicProcessList = dProcessMapper.findByFormWorkflowId(addFormWorkflowDTO.getId());
            if (dynamicProcessList != null && dynamicProcessList.size() != 0) {
                return AjxResult.paramError("该逻辑流程模板被" + dynamicProcessList.size() + "个流程所引用，无法直接操作");
            }
        }
        DynamicForm dForm = dFormMapper.findById(addFormWorkflowDTO.getFormId());
        if (dForm == null) {
            return AjxResult.paramError("表单不存在");
        }
        DynamicWorkflow dWorkflow = dWorkflowMapper.findById(addFormWorkflowDTO.getWorkflowId());
        if (dWorkflow == null) {
            return AjxResult.paramError("逻辑工作流模板不存在");
        }
        try {
            if (addFormWorkflowDTO.getId() == null) {
                if (addFormWorkflowDTO.getDisplayName() == null) {
                    return AjxResult.paramError("参数传递有误");
                } else {
                    if (!Pattern.compile("^[a-zA-Z0-9]{2,50}$").matcher(addFormWorkflowDTO.getDisplayName()).find()) {
                        return AjxResult.paramError("参数传递有误，非法长度或非法字符");
                    }
                    FormWorkflow formWorkflow = formWorkflowMapper.findByDisplayName(addFormWorkflowDTO.getDisplayName());
                    if (formWorkflow != null) {
                        return AjxResult.paramError("逻辑工作流模板名称已存在");
                    }
                    String autorityName = "sys:formWorkflow:" + addFormWorkflowDTO.getDisplayName();
                    Permission permission = permissionMapper.findByName(autorityName);
                    if (permission != null) {
                        return AjxResult.paramError("逻辑工作流模板名称对应的权限名称 [" + addFormWorkflowDTO.getDisplayName() + "] 已存在，请删除后重试");
                    }
                    permission = new Permission();
                    permission.setAuthorityName(autorityName);
                    permission.setMenuId(-1L);
                    permission.setAuthorityAlias(addFormWorkflowDTO.getDisplayName() + ":逻辑工作流模板权限");
                    permissionMapper.addPermission(permission);
                    formWorkflow = new FormWorkflow();
                    BeanUtils.copyProperties(addFormWorkflowDTO, formWorkflow);
                    formWorkflow.setCreatorId(Long.valueOf(BaseContext.getInfo().get("userId").toString()));
                    formWorkflow.setCreatorUsername(String.valueOf(BaseContext.getInfo().get("username")));
                    formWorkflow.setPermissionId(permission.getId());
                    formWorkflowMapper.addFormWorkflow(formWorkflow);
                    return AjxResult.success(formWorkflow.getId());
                }
            } else {
                FormWorkflow formWorkflow = formWorkflowMapper.findById(addFormWorkflowDTO.getId());
                if (formWorkflow == null) {
                    return AjxResult.paramError("逻辑工作流不存在");
                } else {
                    List<DynamicProcess> dynamicProcessList = dProcessMapper.findByFormWorkflowId(addFormWorkflowDTO.getId());
                    if (dynamicProcessList != null && dynamicProcessList.size() != 0) {
                        return AjxResult.paramError("该逻辑流程模板被" + dynamicProcessList.size() + "个流程所引用，无法直接操作");
                    }
                }
                if (!Objects.equals(addFormWorkflowDTO.getDisplayName(), formWorkflow.getDisplayName())) {
                    FormWorkflow tempFormWorkflow = formWorkflowMapper.findByDisplayName(addFormWorkflowDTO.getDisplayName());
                    if (tempFormWorkflow != null) {
                        return AjxResult.paramError("逻辑工作流模板名称已存在");
                    } else {
                        formWorkflow.setDisplayName(addFormWorkflowDTO.getDisplayName());
                    }
                }
                formWorkflow.setFormId(addFormWorkflowDTO.getFormId());
                formWorkflow.setWorkflowId(addFormWorkflowDTO.getWorkflowId());
                formWorkflow.setExplain(addFormWorkflowDTO.getExplain());
                formWorkflowMapper.updateFormWorkflow(formWorkflow);
                return AjxResult.success(formWorkflow.getId());
            }
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Transactional
    @Override
    public AjxResult updateExplain(UpdateExplainDTO updateExplainDTO) {
        if (updateExplainDTO == null || updateExplainDTO.getId() == null || updateExplainDTO.getExplain() == null) {
            return AjxResult.paramError("参数传递有误");
        }
        try {
            FormWorkflow formWorkflow = formWorkflowMapper.findById(updateExplainDTO.getId());
            if (formWorkflow == null) {
                return AjxResult.paramError("逻辑工作流模板不存在");
            }
            formWorkflowMapper.updateExplain(updateExplainDTO.getId(), updateExplainDTO.getExplain());
            return AjxResult.success("更新成功");
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Override
    public PageDTO findFormWorkflowByCondition(FindFormWorkflowPageQueryDTO findFormWorkflowPageQueryDTO) {
        PageVo page = findFormWorkflowPageQueryDTO.getPage();
        if (page == null) {
            logger.warn(LoggerHead.warnHead() + "findFormWorkflowPageQueryDTO.page is Null!");
            return null;
        }
        page.setCurrentIndex((long) (page.getCurrentPage() - 1) * page.getPageSize());
        List<FormWorkflow> formWorkflowList = formWorkflowMapper.findFormWorkflowByCondition(findFormWorkflowPageQueryDTO);
        if (formWorkflowList == null || formWorkflowList.size() == 0) {
            return null;
        }
        // 对结果进行封装和调整
        List<Long> formIdList = new ArrayList<>(), workflowIdList = new ArrayList<>(), permissionIdList = new ArrayList<>();
        List<FormWorkflowVO> formWorkflowVOList = new ArrayList<>();
        for (FormWorkflow formWorkflow : formWorkflowList) {
            // 1、提取 formId、workflowId、permissionId
            formIdList.add(formWorkflow.getFormId());
            workflowIdList.add(formWorkflow.getWorkflowId());
            permissionIdList.add(formWorkflow.getPermissionId());
            // 2、封装成
            FormWorkflowVO formWorkflowVO = new FormWorkflowVO();
            BeanUtils.copyProperties(formWorkflow, formWorkflowVO);
            formWorkflowVOList.add(formWorkflowVO);
        }
        Map<Long, Map<String, String>> formMap = dFormMapper.findMapByIdList(formIdList);
        Map<Long, Map<String, String>> workflowMap = dWorkflowMapper.findMapByIdList(workflowIdList);
        Map<Long, Map<String, String>> permissionMap = permissionMapper.findMapByIdList(permissionIdList);
        for (FormWorkflowVO formWorkflowVO : formWorkflowVOList) {
            formWorkflowVO.setFormDisplayName(formMap.get(formWorkflowVO.getFormId()) != null ? formMap.get(formWorkflowVO.getFormId()).get("display_name") : null);
            formWorkflowVO.setWorkflowDisplayName(workflowMap.get(formWorkflowVO.getWorkflowId()) != null ? workflowMap.get(formWorkflowVO.getWorkflowId()).get("display_name") : null);
            formWorkflowVO.setPermissionDisplayName((permissionMap.get(formWorkflowVO.getPermissionId()) != null ? permissionMap.get(formWorkflowVO.getPermissionId()).get("authority_name") : null));
        }
        page.setCount(formWorkflowMapper.findFormWorkflowByConditionCount(findFormWorkflowPageQueryDTO));
        return new PageDTO(formWorkflowVOList, page);
    }

    @Transactional
    @Override
    public AjxResult removeFormWorkflow(RemoveFormWorkflowDTO removeFormWorkflowDTO) {
        if (removeFormWorkflowDTO == null || removeFormWorkflowDTO.getId() == null) {
            return AjxResult.paramError("参数传递异常");
        }
        try {
            FormWorkflow formWorkflow = formWorkflowMapper.findById(removeFormWorkflowDTO.getId());
            if (formWorkflow == null) {
                return AjxResult.paramError("逻辑工作流不存在");
            } else {
                List<DynamicProcess> dynamicProcessList = dProcessMapper.findByFormWorkflowId(removeFormWorkflowDTO.getId());
                if (dynamicProcessList != null && dynamicProcessList.size() != 0) {
                    return AjxResult.paramError("该逻辑流程模板被" + dynamicProcessList.size() + "个流程所引用，无法直接操作");
                }
                dynamicProcessList = dProcessMapper.findByFormWorkflowId(removeFormWorkflowDTO.getId());
                if (dynamicProcessList != null && dynamicProcessList.size() != 0) {
                    return AjxResult.paramError("该逻辑流程模板被" + dynamicProcessList.size() + "个流程所引用，无法直接操作");
                }
            }
            formWorkflowMapper.remove(removeFormWorkflowDTO.getId());
            return permissionService.removePermission(formWorkflow.getPermissionId());
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Override
    public AjxResult findExistenceByFormIdOrWorkflowId(FindExistenceByFormIdOrWorkflowIdDTO findExistenceByFormIdOrWorkflowIdDTO) {
        if (findExistenceByFormIdOrWorkflowIdDTO == null || (findExistenceByFormIdOrWorkflowIdDTO.getFormId() == null && findExistenceByFormIdOrWorkflowIdDTO.getWorkflowId() == null)) {
            return AjxResult.paramError("参数传递有误");
        }
        if (findExistenceByFormIdOrWorkflowIdDTO.getFormId() != null) {
            List<FormWorkflow> formWorkflowByFormId = formWorkflowMapper.findFormWorkflowByFormId(findExistenceByFormIdOrWorkflowIdDTO.getFormId());
            if (formWorkflowByFormId != null && formWorkflowByFormId.size() != 0) {
                return AjxResult.paramError("该表单模板已被" + formWorkflowByFormId.size() + "个逻辑流程模板引用，无法直接操作");
            }
        } else {
            List<FormWorkflow> formWorkflowByWorkflowId = formWorkflowMapper.findFormWorkflowByWorkflowId(findExistenceByFormIdOrWorkflowIdDTO.getWorkflowId());
            if (formWorkflowByWorkflowId != null && formWorkflowByWorkflowId.size() != 0) {
                return AjxResult.paramError("该审批流模板已被" + formWorkflowByWorkflowId.size() + "个逻辑流程模板引用，无法直接操作");
            }
        }
        return AjxResult.success("未被引用可操作");
    }

    @Transactional
    @Override
    public AjxResult findFormWorkflowSelectData(FindFormWorkflowSelectData findFormWorkflowSelectData) {
        if (findFormWorkflowSelectData == null || findFormWorkflowSelectData.getDisplayName() == null) {
            return AjxResult.paramError("参数传递有误");
        }
        try {
            return AjxResult.success(formWorkflowMapper.findFormWorkflowSelectData(findFormWorkflowSelectData.getDisplayName()));
        } catch (Exception e) {
            logger.error(e.toString());
            return AjxResult.unknownError("数据库操作异常");
        }
    }
}
